import { ref } from 'vue'
import { ElMessage } from 'element-plus'
import { getToken } from '@/utils/webStorage'

let headerTimer;

class WebSocketClient {
  constructor() {
    this.ws = null
    this.isConnected = ref(false)
    this.messageHandlers = new Map()
    this.reconnectAttempts = 0
    this.maxReconnectAttempts = 5
    this.reconnectDelay = 1000
    this.currentToken = null
    this.shouldReconnect = true // 控制是否应该重连

    // 从全局配置获取WebSocket URL
    this.baseWsUrl = window.config_global?.websocketUrl || 'ws://127.0.0.1:8080/app/socket/'
  }

  	//心跳检测
	sendHeader() {
		// 清理已存在的心跳定时器
		if (headerTimer) {
			clearInterval(headerTimer);
			headerTimer = null;
		}

		headerTimer = setInterval(() => {
			// 只在连接开启状态下发送心跳
			if (!this.isConnected.value) {
				clearInterval(headerTimer);
				headerTimer = null;
				return;
			}

			let message = {
				type: 'ping',
				data: {}
			}
      this.ws.send(JSON.stringify(message))

		}, 30000);
	}

  // 初始化WebSocket连接
  initConnect(forceReconnect = false) {
    const token = getToken()

    if (!token) {
      console.warn('未找到token，无法建立WebSocket连接')
      ElMessage.warning('用户未登录，无法建立实时连接')
      return Promise.reject(new Error('No token available'))
    }

    // 如果已连接且token未变化，则返回
    if (this.ws && this.isConnected.value && this.currentToken === token && !forceReconnect) {
      console.log('WebSocket已连接，token未变化')
      return Promise.resolve()
    }

    // 如果token变化了，先关闭旧连接
    if (this.currentToken !== token && this.ws) {
      console.log('Token已更新，重新建立连接')
      this.close()
    }

    this.currentToken = token
    this.shouldReconnect = true // 重新启用重连
    const wsUrl = this.buildWebSocketUrl(token)

    console.log('使用token初始化WebSocket连接:', `***${token.slice(-6)}`)
    return this.connect(wsUrl)
  }

  // 构建WebSocket URL（包含token）
  buildWebSocketUrl(token) {
    // 确保baseWsUrl以/结尾
    const baseUrl = this.baseWsUrl.endsWith('/') ? this.baseWsUrl : this.baseWsUrl + '/'

    // 构建格式：app/socket/{token}
    const wsUrl = `${baseUrl}${token}`

    console.log('构建WebSocket URL:', wsUrl)
    return wsUrl
  }

  // 连接WebSocket
  connect(url) {
    console.log('=== 开始建立WebSocket连接 ===')
    console.log('连接URL:', url.replace(/\/[^\/]+$/, '/***TOKEN***')) // 隐藏token
    console.log('当前重连次数:', this.reconnectAttempts)

    return new Promise((resolve, reject) => {
      try {
        this.ws = new WebSocket(url)

        this.ws.onopen = () => {
          console.log('✅ WebSocket连接成功，token已通过URL路径验证')
          this.isConnected.value = true
          this.reconnectAttempts = 0
          this.sendHeader()
          resolve()
        }

        this.ws.onclose = (event) => {
          console.log('=== WebSocket连接关闭 ===')
          console.log('关闭代码:', event.code)
          console.log('关闭原因:', event.reason || '无原因')
          console.log('是否为清理关闭:', event.wasClean)
          console.log('重连次数:', this.reconnectAttempts)

          this.isConnected.value = false

          // 获取关闭代码的含义
          const closeReasons = {
            1000: '正常关闭',
            1001: '端点离开',
            1002: '协议错误',
            1003: '不支持的数据类型',
            1005: '未提供状态码',
            1006: '异常关闭',
            1007: '数据格式错误',
            1008: '违反策略',
            1009: '消息过大',
            1010: '缺少扩展',
            1011: '服务器错误',
            1015: 'TLS握手失败'
          }

          console.log('关闭原因解释:', closeReasons[event.code] || '未知错误')

          // 不自动重连的情况
          if (event.code === 1008 || event.code === 1002 || event.code === 1003) {
            console.log('❌ 服务器拒绝连接，停止重连')
            ElMessage.error(`连接被服务器拒绝: ${closeReasons[event.code] || '未知错误'}`)
            return
          }

          // 如果是token相关问题，检查token
          const token = getToken()
          if (!token) {
            console.log('❌ 无有效token，停止重连')
            ElMessage.warning('请先登录后再尝试连接')
            return
          }

          this.handleReconnect()
        }

        this.ws.onerror = (error) => {
          console.error('WebSocket错误:', error)
          reject(error)
        }

        this.ws.onmessage = (event) => {
          try {
            const message = JSON.parse(event.data)
            console.log(message)
            if(message.type === 'count')  {
              sessionStorage.setItem('onlineData', JSON.stringify(message.data))
            }
            this.handleMessage(message)
          } catch (error) {
            console.error('解析消息失败:', error)
          }
        }
      } catch (error) {
        console.error('创建WebSocket连接失败:', error)
        reject(error)
      }
    })
  }

  // 重新连接
  handleReconnect() {
    if (!this.shouldReconnect) {
      console.log('🛑 重连已被禁用，停止重连')
      return
    }

    if (this.reconnectAttempts >= this.maxReconnectAttempts) {
      console.log('❌ 达到最大重连次数，停止重连')
      ElMessage.error('WebSocket连接失败，请刷新页面重试')
      this.shouldReconnect = false
      return
    }

    const delay = this.reconnectDelay * Math.pow(2, this.reconnectAttempts)
    console.log(`⏰ ${delay}ms后尝试重新连接 (${this.reconnectAttempts + 1}/${this.maxReconnectAttempts})`)

    setTimeout(() => {
      if (!this.shouldReconnect) {
        console.log('🛑 重连期间被取消')
        return
      }

      this.reconnectAttempts++
      console.log(`🔄 开始第${this.reconnectAttempts}次重连`)

      const token = getToken()
      if (!token) {
        console.error('❌ 重连失败：无有效token')
        ElMessage.warning('请重新登录后再尝试连接')
        this.shouldReconnect = false
        return
      }

      // 检查token是否发生变化
      if (token !== this.currentToken) {
        console.log('🔄 Token已更新，使用新token重连')
        this.currentToken = token
      }

      const wsUrl = this.buildWebSocketUrl(token)
      this.connect(wsUrl).catch(() => {
        console.log('❌ 重连失败，将继续尝试')
      })
    }, delay)
  }

  // 认证逻辑已移除

  // 发送消息
  send(type, data) {
    if (!this.isConnected.value) {
      ElMessage.error('网络连接已断开，请刷新页面重试')
      return false
    }

    try {
      const message = JSON.stringify({
        type,
        data,
        timestamp: Date.now()
        // token已在WebSocket URL中，无需在每条消息中重复发送
      })
      this.ws.send(message)
      return true
    } catch (error) {
      console.error('发送消息失败:', error)
      ElMessage.error('发送消息失败')
      return false
    }
  }

  // 检查用户在线状态
  // 发送: {"type":"on-line","data":{"uid":"<sender>","targetId":"<receiver>"}}
  // 响应: {"type":"on-line","data":{"uid":"<sender>","targetId":"<receiver>","status":true}}
  checkOnlineStatus(uid, targetId, timeoutMs = 3000) {
    return new Promise((resolve) => {
      if (!this.isConnected.value) {
        ElMessage.error('网络连接已断开，请刷新页面重试')
        resolve(false)
        return
      }

      const req = {
        uid: String(uid),
        targetId: String(targetId)
      }

      const type = 'on-line'
      const handler = (data) => {
        try {
          const match = String(data?.uid) === req.uid && String(data?.targetId) === req.targetId
          if (match) {
            this.off(type, handler)
            resolve(!!data?.status)
          }
        } catch (e) {
          this.off(type, handler)
          resolve(false)
        }
      }

      // 监听一次响应
      this.on(type, handler)
      // 发送请求
      this.send(type, req)
      // 超时兜底
      setTimeout(() => {
        this.off(type, handler)
        resolve(false)
      }, timeoutMs)
    })
  }

  // 注册消息处理器
  on(type, handler) {
    if (!this.messageHandlers.has(type)) {
      this.messageHandlers.set(type, new Set())
    }
    this.messageHandlers.get(type).add(handler)
  }

  // 移除消息处理器
  off(type, handler) {
    if (this.messageHandlers.has(type)) {
      this.messageHandlers.get(type).delete(handler)
    }
  }

  // 处理接收到的消息（移除认证相关分支）
  handleMessage(message) {
    const { type, data } = message
    if (this.messageHandlers.has(type)) {
      this.messageHandlers.get(type).forEach(handler => {
        try {
          handler(data)
        } catch (error) {
          console.error(`处理 ${type} 类型消息失败:`, error)
        }
      })
    }
  }

  // 关闭连接
  close() {
    console.log('🔌 手动关闭WebSocket连接')

    // 停止重连
    this.shouldReconnect = false

    if (this.ws) {
      this.ws.close(1000, '手动关闭') // 正常关闭
      this.ws = null
    }

    this.isConnected.value = false
    this.currentToken = null
    this.reconnectAttempts = 0
  }

  // 检查连接和认证状态
  isReady() {
    return this.isConnected.value
  }

  // 获取连接状态
  getStatus() {
    return {
      connected: this.isConnected.value,
      hasToken: !!this.currentToken
    }
  }

  // 强制重新认证
  reauth() {
    const token = getToken()
    if (token && token !== this.currentToken) {
      console.log('执行重新认证')
      return this.initConnect(true)
    }
    return Promise.resolve()
  }

  // 停止重连
  stopReconnect() {
    console.log('🛑 手动停止重连')
    this.shouldReconnect = false
  }

  // 启用重连
  enableReconnect() {
    console.log('🔄 启用重连')
    this.shouldReconnect = true
    this.reconnectAttempts = 0
  }

  // 获取详细状态信息
  getDetailedStatus() {
    return {
      connected: this.isConnected.value,
      hasToken: !!this.currentToken,
      shouldReconnect: this.shouldReconnect,
      reconnectAttempts: this.reconnectAttempts,
      maxReconnectAttempts: this.maxReconnectAttempts,
      wsUrl: this.baseWsUrl
    }
  }
}

// 创建单例
const wsClient = new WebSocketClient()

// 消息类型常量
export const MessageType = {
  CHAT: 'chat',
  COUNT: 'count',
  ON_LINE: 'on-line',
  MEETING_INVITE: 'meeting_invite',
  MEETING_ACCEPT: 'meeting_accept',
  MEETING_REJECT: 'meeting_reject',
  MEETING_END: 'meeting_end',
  USER_STATUS: 'user_status',
  VOICE_CALL: 'voice-call',
  VIDEO_CALL: 'video-call',
  CALL_AGREE: 'call-agree',
  CALL_REJECT: 'call-reject',
  CALL_END: 'call-end',
  GEN_SESSION: 'gen-session',
  SESSION_ID: 'session-id',
  CHAT_MESSAGE: 'chat-message'
}

export default wsClient
